{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Solution strategies\n",
    "This tutorials demonstrates some of the more advanced solution strategies available in `PorePy`. \n",
    "The tutorial will be supplemented with more strategies as these become available.\n",
    "The model problems are presented succinctly.\n",
    "\n",
    "## Line search for multiphysics problems with fracture deformation (experimental)\n",
    "The combination of highly nonlinear multiphysics problems and the non-smooth formulation of contact mechanics may lead to severe convergence issues.\n",
    "To improve convergence, we provide a line search algorithm tailored to the irregularities of the contact equations, see https://arxiv.org/abs/2407.01184.\n",
    "\n",
    "\n",
    "We define a dummy problem with one fracture and trivial problem data (boundary conditions etc.). \n",
    "This allows us to emphasize the steps needed to invoke the line search algorithm.\n",
    "For more challenging problems which would not converge with regular Newton, please confer the examples of the above manuscript."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import porepy as pp\n",
    "\n",
    "from porepy.applications.md_grids.model_geometries import CubeDomainOrthogonalFractures\n",
    "from porepy.numerics.nonlinear import line_search\n",
    "\n",
    "\n",
    "class TailoredPoromechanics(\n",
    "    # Problem definition\n",
    "    CubeDomainOrthogonalFractures,\n",
    "    # Add nonlinearity to the fracture flow\n",
    "    pp.constitutive_laws.CubicLawPermeability,\n",
    "    # Needed for the tailored line search algorithm\n",
    "    pp.models.solution_strategy.ContactIndicators,\n",
    "    # Base class\n",
    "    pp.poromechanics.Poromechanics,\n",
    "):\n",
    "    \"\"\"Combine mixins with the poromechanics class.\"\"\"\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To invoke the line search, we first define the tailored Newton solver class. We then specify a few parameters, including the \"nonlinear_solver\". "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ConstraintLineSearchNonlinearSolver(\n",
    "    line_search.ConstraintLineSearch,  # The tailoring to contact constraints.\n",
    "    line_search.SplineInterpolationLineSearch,  # Technical implementation of the actual search along given update direction\n",
    "    line_search.LineSearchNewtonSolver,  # General line search.\n",
    "):\n",
    "    \"\"\"Collect all the line search methods in one class.\"\"\"\n",
    "\n",
    "model_params = {\n",
    "    \"fracture_indices\": [1], # Fracture with constant y-coordinate\n",
    "    \"meshing_arguments\": {\"cell_size\": 1 / 4},\n",
    "}\n",
    "solver_params = {\n",
    "    \"nl_convergence_tol_res\": 1e-10, # Since the line search reduces the update, a residual based tolerance is needed\n",
    "    \"nonlinear_solver\": ConstraintLineSearchNonlinearSolver,\n",
    "    \"Global_line_search\": 0,  # Set to 1 to use turn on a residual-based line search\n",
    "    \"Local_line_search\": 1,  # Set to 0 to use turn off the tailored line search\n",
    "    \"adaptive_indicator_scaling\": 1,  # Scale the indicator adaptively to increase robustness\n",
    "}\n",
    "# Run the simulation.\n",
    "model = TailoredPoromechanics(model_params)\n",
    "pp.run_time_dependent_model(model, solver_params)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Some known issues to consider:\n",
    "- The nonlinearity caused by the fracture permeability has proven sensitive to discretization method.\n",
    "TPFA seems considerably more stable than MPFA.\n",
    "For details, see the above mentioned paper.\n",
    "- If regular Newton converges, it may be faster than the line search method.\n",
    "An unexplored option is to use the line search as a fallback if Newton fails to converge."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
